﻿using System;
using System.Collections.Generic;
using System.Linq;
using NopSolutions.NopCommerce.BusinessLogic;
using NopSolutions.NopCommerce.BusinessLogic.Infrastructure;
using NopSolutions.NopCommerce.BusinessLogic.Model;
using NopSolutions.NopCommerce.BusinessLogic.Providers;
using NopSolutions.NopCommerce.BusinessLogic.Services;
using NopSolutions.NopCommerce.BusinessLogic.Utils;
using NopSolutions.NopCommerce.Common;

namespace Cmd.Shipping.NemoExpress
{
    public class NemoExpressComputationMethod : IShippingRateComputationMethod
    {
        private const string NEMO_EXPRESS_SHIPPING = "Cmd.Shipping.NemoExpress.ShippingMethod.{0}";

        #region IShippingRateComputationMethod Members

        public List<ShippingOption> GetShippingOptions(ShipmentPackage shipmentPackage, ref string error) {
            var shippingOptionCollection = new List<ShippingOption>();
            if (shipmentPackage == null) {
                throw new ArgumentNullException("ShipmentPackage");
            }
            if (shipmentPackage.Items == null) {
                throw new NopException("No shipment items");
            }
            decimal num = new decimal(0);
            foreach (ShoppingCartItem item in shipmentPackage.Items) {
                if (!item.IsFreeShipping) {
                    num = num + PriceHelper.GetSubTotal(item, shipmentPackage.Customer, true);
                }
            }
            decimal shoppingCartTotalWeigth = IoC.Resolve<IShippingService>().GetShoppingCartTotalWeight(shipmentPackage.Items, NopContext.Current.User);
            var allShippingMethods = IoC.Resolve<IShippingService>().GetAllShippingMethods();
            foreach (var shippingMethod in allShippingMethods) {
                var shippingOption = new ShippingOption();
                shippingOption.Name = shippingMethod.Name;
                shippingOption.Description = shippingMethod.Description;
                shippingOption.Rate = GetRate(num, shoppingCartTotalWeigth, shippingMethod.ShippingMethodId);
                shippingOptionCollection.Add(shippingOption);
            }
            return shippingOptionCollection;
        }

        public decimal? GetFixedRate(ShipmentPackage shipmentPackage) {
            return decimal.Zero;
        }

        public decimal GetRate(Decimal subTotal, Decimal weight, int shippingMethodId) {
            var settingManager = IoC.Resolve<ISettingService>();

            string key = string.Format(NEMO_EXPRESS_SHIPPING, shippingMethodId);
            var fixedRateShippingMethod = settingManager.GetSettingByName(key);
            if (fixedRateShippingMethod != null) {
                return settingManager.GetSettingValueDecimalNative(key);
            }

            decimal firstKiloPrice = settingManager.GetSettingValueDecimalNative("Cmd.Shipping.NemoExpress.FirstKiloPrice");
            decimal everyotherKiloPrice = settingManager.GetSettingValueDecimalNative("Cmd.Shipping.NemoExpress.EveryotherKiloPrice");
            decimal pickupTax = settingManager.GetSettingValueDecimalNative("Cmd.Shipping.NemoExpress.PickupTax");
            decimal pickupPercentFromValue = settingManager.GetSettingValueDecimalNative("Cmd.Shipping.NemoExpress.PickupPercentFromValue");

            TaxRate taxRate = null;
            if (NopContext.Current.User != null)
                if (NopContext.Current.User.ShippingAddress != null)
                    taxRate = IoC.Resolve<ITaxRateService>().GetAllTaxRates().Where<TaxRate>(new Func<TaxRate, bool>((t) => t.CountryId == NopContext.Current.User.ShippingAddress.CountryId)).SingleOrDefault<TaxRate>();

            // hardcode default vat for romania
            decimal percentage = 24;
            if (taxRate != null)
                percentage = taxRate.Percentage;

            // (everyotherKiloPrice * (weight - 1) + firstKiloPrice + PickupTax + (subTotal * pickupPercentFromValue/100)) * tva

            decimal rate = (everyotherKiloPrice * weight-- + firstKiloPrice + pickupTax + (subTotal * (pickupPercentFromValue / 100))) * ((percentage / 100) + 1);
            return rate;
        }

        public ShippingRateComputationMethodTypeEnum ShippingRateComputationMethodType {
            get { return ShippingRateComputationMethodTypeEnum.Offline; }
        }

        #endregion
    }
}
